//go:build linux
// +build linux

package utils

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"gitee.com/liumou_site/go-network-monitoring/types"
)

// GetProcessTrafficStats 获取进程的网络流量统计
func GetProcessTrafficStats(pid int32) (*types.ProcessTrafficSnapshot, error) {
	// 读取 /proc/[pid]/net/dev 文件
	devPath := fmt.Sprintf("/proc/%d/net/dev", pid)

	// 检查文件是否存在
	if _, err := os.Stat(devPath); os.IsNotExist(err) {
		// 如果进程特定的net/dev不存在，尝试从全局netstat获取
		return getProcessTrafficFromNetstat(pid)
	}

	return readProcessNetDev(pid, devPath)
}

// readProcessNetDev 读取进程的net/dev文件
func readProcessNetDev(pid int32, devPath string) (*types.ProcessTrafficSnapshot, error) {
	file, err := os.Open(devPath)
	if err != nil {
		// 文件不存在时，返回零值快照
		return &types.ProcessTrafficSnapshot{
			PID:       pid,
			Timestamp: time.Now(),
			TotalSent: 0,
			TotalRecv: 0,
		}, nil
	}
	defer file.Close()

	var totalSent, totalRecv uint64
	scanner := bufio.NewScanner(file)

	// 跳过前两行头部信息
	for i := 0; i < 2 && scanner.Scan(); i++ {
		// skip headers
	}

	// 解析网络接口数据
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}

		fields := strings.Fields(line)
		if len(fields) < 17 {
			continue
		}

		// fields[1] = bytes received, fields[9] = bytes transmitted
		recv, err1 := strconv.ParseUint(fields[1], 10, 64)
		sent, err2 := strconv.ParseUint(fields[9], 10, 64)

		if err1 == nil && err2 == nil {
			totalRecv += recv
			totalSent += sent
		}
	}

	return &types.ProcessTrafficSnapshot{
		PID:       pid,
		Timestamp: time.Now(),
		TotalSent: totalSent,
		TotalRecv: totalRecv,
	}, nil
}

// getProcessTrafficFromNetstat 从系统全局统计中获取进程流量（备用方案）
func getProcessTrafficFromNetstat(pid int32) (*types.ProcessTrafficSnapshot, error) {
	// 这是一个备用方案，当无法直接读取进程的net/dev时使用
	// 实际实现中，我们可能需要通过其他方式获取进程的网络流量
	// 比如通过解析 /proc/net/tcp, /proc/net/udp 和对应的流量统计

	snapshot, err := getProcessTrafficFromConnections(pid)
	if err != nil {
		// 如果都失败了，返回零值
		return &types.ProcessTrafficSnapshot{
			PID:       pid,
			Timestamp: time.Now(),
			TotalSent: 0,
			TotalRecv: 0,
		}, nil
	}

	return snapshot, nil
}

// getProcessTrafficFromConnections 通过连接信息推算流量（近似值）
func getProcessTrafficFromConnections(pid int32) (*types.ProcessTrafficSnapshot, error) {
	// 读取 /proc/net/snmp 获取系统级别的网络统计
	snmpStats, err := readSNMPStats()
	if err != nil {
		return nil, err
	}

	// 获取进程的连接数
	connCount, err := getProcessConnectionCount(pid)
	if err != nil {
		return nil, err
	}

	// 简化估算：假设流量平均分配到所有连接
	// 这是一个粗略的估计，实际应用中需要更精确的方法
	totalConnections := getTotalConnectionCount()
	if totalConnections == 0 {
		totalConnections = 1 // 避免除零
	}

	estimatedSent := snmpStats.TotalSent * uint64(connCount) / uint64(totalConnections)
	estimatedRecv := snmpStats.TotalRecv * uint64(connCount) / uint64(totalConnections)

	return &types.ProcessTrafficSnapshot{
		PID:       pid,
		Timestamp: time.Now(),
		TotalSent: estimatedSent,
		TotalRecv: estimatedRecv,
	}, nil
}

// SNMPStats 系统SNMP网络统计
type SNMPStats struct {
	TotalSent uint64
	TotalRecv uint64
}

// readSNMPStats 读取系统网络统计
func readSNMPStats() (*SNMPStats, error) {
	file, err := os.Open("/proc/net/snmp")
	if err != nil {
		return nil, err
	}
	defer file.Close()

	stats := &SNMPStats{}
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		line := scanner.Text()
		if strings.HasPrefix(line, "Ip: ") && strings.Contains(line, "InOctets") {
			// 读取下一行的数值
			if scanner.Scan() {
				values := strings.Fields(scanner.Text())
				if len(values) >= 10 {
					if recv, err := strconv.ParseUint(values[8], 10, 64); err == nil {
						stats.TotalRecv = recv
					}
					if sent, err := strconv.ParseUint(values[9], 10, 64); err == nil {
						stats.TotalSent = sent
					}
				}
			}
			break
		}
	}

	return stats, nil
}

// getProcessConnectionCount 获取进程的连接数
func getProcessConnectionCount(pid int32) (int, error) {
	count := 0

	// 检查TCP连接
	tcpFiles := []string{"/proc/net/tcp", "/proc/net/tcp6"}
	for _, file := range tcpFiles {
		c, err := countProcessConnections(file, pid)
		if err == nil {
			count += c
		}
	}

	// 检查UDP连接
	udpFiles := []string{"/proc/net/udp", "/proc/net/udp6"}
	for _, file := range udpFiles {
		c, err := countProcessConnections(file, pid)
		if err == nil {
			count += c
		}
	}

	return count, nil
}

// countProcessConnections 统计指定进程在某个网络文件中的连接数
func countProcessConnections(netFile string, targetPid int32) (int, error) {
	file, err := os.Open(netFile)
	if err != nil {
		return 0, err
	}
	defer file.Close()

	count := 0
	scanner := bufio.NewScanner(file)

	// 跳过头部
	if scanner.Scan() {
		// skip header
	}

	for scanner.Scan() {
		line := scanner.Text()
		fields := strings.Fields(line)
		if len(fields) < 10 {
			continue
		}

		// 获取inode
		inode := fields[9]
		if inode == "0" {
			continue
		}

		// 通过inode查找进程PID
		if pid := findPidByInode(inode); pid == targetPid {
			count++
		}
	}

	return count, nil
}

// findPidByInode 通过inode查找进程PID
func findPidByInode(inode string) int32 {
	procDirs, err := filepath.Glob("/proc/[0-9]*/fd/*")
	if err != nil {
		return 0
	}

	for _, fdPath := range procDirs {
		if link, err := os.Readlink(fdPath); err == nil {
			if strings.Contains(link, "socket:["+inode+"]") {
				// 从路径中提取PID
				parts := strings.Split(fdPath, "/")
				if len(parts) >= 3 {
					if pid, err := strconv.ParseInt(parts[2], 10, 32); err == nil {
						return int32(pid)
					}
				}
			}
		}
	}

	return 0
}

// getTotalConnectionCount 获取系统总连接数
func getTotalConnectionCount() int {
	count := 0

	files := []string{"/proc/net/tcp", "/proc/net/tcp6", "/proc/net/udp", "/proc/net/udp6"}
	for _, file := range files {
		if f, err := os.Open(file); err == nil {
			scanner := bufio.NewScanner(f)
			// 跳过头部
			if scanner.Scan() {
				// skip header
			}
			for scanner.Scan() {
				count++
			}
			f.Close()
		}
	}

	return count
}

// CalculateProcessSpeed 计算进程网络速度
func CalculateProcessSpeed(prev, current *types.ProcessTrafficSnapshot) *types.ProcessSpeedStats {
	if prev == nil || current == nil {
		return &types.ProcessSpeedStats{
			PID:               current.PID,
			DownloadSpeedBps:  0,
			UploadSpeedBps:    0,
			DownloadSpeedMbps: 0,
			UploadSpeedMbps:   0,
			LastUpdate:        time.Now().Format("2006-01-02 15:04:05"),
			DownloadSpeedText: "0 B/s",
			UploadSpeedText:   "0 B/s",
		}
	}

	// 计算时间差（秒）
	timeDiff := current.Timestamp.Sub(prev.Timestamp).Seconds()
	if timeDiff <= 0 {
		timeDiff = 1 // 避免除零
	}

	// 计算字节差
	sentDiff := int64(current.TotalSent) - int64(prev.TotalSent)
	recvDiff := int64(current.TotalRecv) - int64(prev.TotalRecv)

	// 处理负值（可能由于统计重置）
	if sentDiff < 0 {
		sentDiff = 0
	}
	if recvDiff < 0 {
		recvDiff = 0
	}

	// 计算速度 (字节/秒)
	uploadSpeedBps := float64(sentDiff) / timeDiff
	downloadSpeedBps := float64(recvDiff) / timeDiff

	// 转换为Mbps
	uploadSpeedMbps := uploadSpeedBps * 8 / 1024 / 1024
	downloadSpeedMbps := downloadSpeedBps * 8 / 1024 / 1024

	return &types.ProcessSpeedStats{
		PID:               current.PID,
		DownloadSpeedBps:  downloadSpeedBps,
		UploadSpeedBps:    uploadSpeedBps,
		DownloadSpeedMbps: downloadSpeedMbps,
		UploadSpeedMbps:   uploadSpeedMbps,
		LastUpdate:        current.Timestamp.Format("2006-01-02 15:04:05"),
		DownloadSpeedText: FormatSpeed(downloadSpeedBps),
		UploadSpeedText:   FormatSpeed(uploadSpeedBps),
	}
}
